﻿#if defined(_WIN32)

#include	"Engine.System.hpp"

#include	<windows.h>
#include	<direct.h>
#include	<io.h>

#include	<cstring>
#include	<ctime>
#include	<vector>

namespace Engine { namespace System { namespace Path {

	bool Exists(const std::string & szPath) {
		return _access(szPath.c_str(), 0) == 0;
	}

	bool Create(const std::string & szPath) {
		return _mkdir(szPath.c_str()) == 0;
	}

	std::string Current() {
		std::string szPath(512, '\0');
		_getcwd((char *)szPath.c_str(), 512);
		return std::move(szPath);
	}

	std::string Change(const std::string & szPath) {
		_chdir(szPath.c_str());
		return Current();
	}

	void ForEachFile(const std::string & szRoot, bool bIntoSub, void(*pOpt)(const std::string &)) {
		WIN32_FIND_DATAA iFind;
		HANDLE hResult;
		std::vector<std::string> vSubDir;

		std::string szFinder(szRoot);
		szFinder.append("\\*.*");

		hResult = ::FindFirstFileA(szFinder.c_str(), &iFind);
		if (hResult == INVALID_HANDLE_VALUE)
			return;
		
		while (::FindNextFileA(hResult, &iFind)) {
			std::string szData(szRoot);
			szData.append("\\");
			szData.append(iFind.cFileName);
			if ((iFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && bIntoSub) {
				if (strcmp(iFind.cFileName, ".") == 0 || strcmp(iFind.cFileName, "..") == 0)
					continue;
				else
					vSubDir.push_back(szData);
			} else {
				pOpt(szData);
			}
		}

		::FindClose(hResult);

		for (size_t nIdx = 0; nIdx < vSubDir.size(); ++nIdx)
			ForEachFile(vSubDir[nIdx], true, pOpt);
	}

}}}

namespace Engine { namespace System {

	Time Time::Current() {
		Time		iInfo;
		SYSTEMTIME	iSys;

		::GetLocalTime(&iSys);

		iInfo.nUnixSec	= time(0);
		iInfo.nYear		= iSys.wYear;
		iInfo.nMonth	= iSys.wMonth;
		iInfo.nDay	 	= iSys.wDay;
		iInfo.nWeek		= iSys.wDayOfWeek;
		iInfo.nHour		= iSys.wHour;
		iInfo.nMinute	= iSys.wMinute;
		iInfo.nSecond	= iSys.wSecond;
		iInfo.nMilliSec	= iSys.wMilliseconds;

		return std::move(iInfo);
	}

	Time Time::Convert(time_t nUnixSec) {
		Time		iInfo;
		struct tm	iTime;

		localtime_s(&iTime, &nUnixSec);
		
		iInfo.nUnixSec	= nUnixSec;
		iInfo.nYear		= iTime.tm_year + 1900;
		iInfo.nMonth	= iTime.tm_mon + 1;
		iInfo.nDay	 	= iTime.tm_mday + 1;
		iInfo.nWeek		= iTime.tm_wday;
		iInfo.nHour		= iTime.tm_hour;
		iInfo.nMinute	= iTime.tm_min;
		iInfo.nSecond	= iTime.tm_sec;
		iInfo.nMilliSec	= 0;

		return std::move(iInfo);
	}

	uint64_t Time::Tick() {
		return ::GetTickCount();
	}

}}

#endif
